package com.asen.commons.core.jdbc.handler;

import com.asen.commons.core.base.enums.DictTypeEnum;
import com.asen.commons.core.base.domain.Core;
import com.asen.commons.core.meta.entity.EntityObject;
import com.asen.commons.core.meta.loader.EntityObjectLoader;
import com.asen.commons.core.base.IntegerEnum;
import com.asen.commons.core.base.StringEnum;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 类型处理器容器
 *
 * @author Gary
 * @version 1.0
 * @date 2018-11-29
 */
public class TypeHandlerHolder {

    private final static Map<Class<?>, TypeHandler<?>> TYPE_HANDLER_MAP = new ConcurrentHashMap<Class<?>, TypeHandler<?>>();

    private final static Map<Class<?>, TypeHandler<?>> LIST_HANDLER_MAP = new ConcurrentHashMap<Class<?>, TypeHandler<?>>();

    private final static Map<DictTypeEnum, TypeHandler<?>> DICT_HANDLER_MAP = new ConcurrentHashMap<DictTypeEnum, TypeHandler<?>>();

    static {
        TYPE_HANDLER_MAP.put(Boolean.class, new BooleanTypeHandler());
        TYPE_HANDLER_MAP.put(boolean.class, new BooleanTypeHandler());

        TYPE_HANDLER_MAP.put(Integer.class, new IntegerTypeHandler());
        TYPE_HANDLER_MAP.put(int.class, new IntegerTypeHandler());

        TYPE_HANDLER_MAP.put(Long.class, new LongTypeHandler());
        TYPE_HANDLER_MAP.put(long.class, new LongTypeHandler());

        TYPE_HANDLER_MAP.put(String.class, new StringTypeHandler());

        TYPE_HANDLER_MAP.put(BigDecimal.class, new BigDecimalTypeHandler());

        TYPE_HANDLER_MAP.put(Date.class, new DateTypeHandler());

        TYPE_HANDLER_MAP.put(java.sql.Date.class, new SqlDateTypeHandler());
        TYPE_HANDLER_MAP.put(java.sql.Timestamp.class, new SqlTimestampTypeHandler());

        TYPE_HANDLER_MAP.put(Character.class, new CharacterTypeHandler());
        TYPE_HANDLER_MAP.put(char.class, new CharacterTypeHandler());

    }

    //public static TypeHandler<?> getDictHandler(DictTypeEnum dictType) {
    //    TypeHandler handler = DICT_HANDLER_MAP.get(dictType);
    //
    //    if (handler != null) {
    //        return handler;
    //    }
    //
    //    handler = new DictTypeHandler(dictType);
    //    DICT_HANDLER_MAP.put(dictType, handler);
    //    return handler;
    //}

    public static TypeHandler<?> getListHandler(Class<?> clazz) {
        TypeHandler handler = LIST_HANDLER_MAP.get(clazz);

        if (handler != null) {
            return handler;
        }

        handler = new ListTypeHandler(clazz);
        LIST_HANDLER_MAP.put(clazz, handler);
        return handler;
    }

    public static TypeHandler<?> getHandler(Class<?> clazz) {
        TypeHandler handler = TYPE_HANDLER_MAP.get(clazz);

        if (handler != null) {
            return handler;
        }

        if (StringEnum.class.isAssignableFrom(clazz)) {
            handler = new StringEnumHandler(clazz);
            TYPE_HANDLER_MAP.put(clazz, handler);
            return handler;
        }

        if (IntegerEnum.class.isAssignableFrom(clazz)) {
            handler = new IntegerEnumHandler(clazz);
            TYPE_HANDLER_MAP.put(clazz, handler);
            return handler;
        }

        if (Core.class.isAssignableFrom(clazz)) {
            handler = new CoreDoTypeHandler(clazz);
            TYPE_HANDLER_MAP.put(clazz, handler);
            return handler;
        }

        EntityObject eo = EntityObjectLoader.getInstance().load(clazz);
        if (eo.hasField("id")) {
            handler = new ModelTypeHandler(clazz);
            TYPE_HANDLER_MAP.put(clazz, handler);
            return handler;
        }

        return null;
    }

    public static Map<Class<?>, TypeHandler<?>> getHandlerMap() {
        return TYPE_HANDLER_MAP;
    }
}
